<!doctype html>
<html class="no-js" lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>angular-oauth2-oidc</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="icon" type="image/x-icon" href="../images/favicon.ico">
	   <link rel="stylesheet" href="../styles/style.css">
        <link rel="stylesheet" href="../styles/dark.css">
    </head>
    <body>
          <script>
               // Blocking script to avoid flickering dark mode
               // Dark mode toggle button
               var useDark = window.matchMedia('(prefers-color-scheme: dark)');
               var darkModeState = useDark.matches;
               var $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
               var $darkModeToggles = document.querySelectorAll('.dark-mode-switch');
               var darkModeStateLocal = localStorage.getItem('compodoc_darkmode-state');

               function checkToggle(check) {
                    for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
                         $darkModeToggleSwitchers[i].checked = check;
                    }
               }

               function toggleDarkMode(state) {
                    if (window.localStorage) {
                         localStorage.setItem('compodoc_darkmode-state', state);
                    }

                    checkToggle(state);

                    const hasClass = document.body.classList.contains('dark');

                    if (state) {
                         for (var i = 0; i < $darkModeToggles.length; i++) {
                              $darkModeToggles[i].classList.add('dark');
                         }
                         if (!hasClass) {
                              document.body.classList.add('dark');
                         }
                    } else {
                         for (var i = 0; i < $darkModeToggles.length; i++) {
                              $darkModeToggles[i].classList.remove('dark');
                         }
                         if (hasClass) {
                              document.body.classList.remove('dark');
                         }
                    }
               }

               useDark.addEventListener('change', function (evt) {
                    toggleDarkMode(evt.matches);
               });
               if (darkModeStateLocal) {
                    darkModeState = darkModeStateLocal === 'true';
               }
               toggleDarkMode(darkModeState);
          </script>

        <div class="navbar navbar-default navbar-fixed-top d-md-none p-0">
               <div class="d-flex">
                    <a href="../" class="navbar-brand">angular-oauth2-oidc</a>
                    <button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button>
               </div>
        </div>

        <div class="xs-menu menu" id="mobile-menu">
                <div id="book-search-input" role="search"><input type="text" placeholder="Type to search"></div>            <compodoc-menu></compodoc-menu>
        </div>

        <div class="container-fluid main">
           <div class="row main">
               <div class="d-none d-md-block menu">
                   <compodoc-menu mode="normal"></compodoc-menu>
               </div>
               <!-- START CONTENT -->
               <div class="content additional-page">
                   <div class="content-data">





















<h1>Using Password-Flow</h1>
<p>This section shows how to use the password flow, which demands the user to directly enter his or her password into the client.</p>
<p>Please note that from an OAuth2/OIDC perspective, the code flow is better suited for logging into a SPA and the flow described here should only be used,
when a) there is a strong trust relations ship between the client and the auth server and when b) other flows are not possible.</p>
<p>Please also note that with <strong>OAuth 2.1</strong>, <strong>password flow</strong> will be <strong>deprecated</strong>. </p>
<h2>Configure Library for Password Flow (using discovery document)</h2>
<p>To configure the library you just have to set some properties on startup. For this, the following sample uses the constructor of the AppComponent which is called before routing kicks in.</p>
<p>Please not, that this configuration is quite similar to the one for the implcit flow.</p>
<b>Example :</b><div><pre class="line-numbers"><code class="language-TypeScript">&#64;Component({ ... })
export class AppComponent {

  constructor(private oauthService: OAuthService) {

        // The SPA&#39;s id. Register SPA with this id at the auth-server
        this.oauthService.clientId = &quot;demo-resource-owner&quot;;

        // set the scope for the permissions the client should request
        // The auth-server used here only returns a refresh token (see below), when the scope offline_access is requested
        this.oauthService.scope = &quot;openid profile email voucher offline_access&quot;;

        // Use setStorage to use sessionStorage or another implementation of the TS-type Storage
        // instead of localStorage
        this.oauthService.setStorage(sessionStorage);

        // Set a dummy secret
        // Please note that the auth-server used here demand the client to transmit a client secret, although
        // the standard explicitly cites that the password flow can also be used without it. Using a client secret
        // does not make sense for a SPA that runs in the browser. That&#39;s why the property is called dummyClientSecret
        // Using such a dummy secret is as safe as using no secret.
        this.oauthService.dummyClientSecret = &quot;geheim&quot;;

        // Load Discovery Document and then try to login the user
        let url = &#39;https://steyer-identity-server.azurewebsites.net/identity/.well-known/openid-configuration&#39;;
        this.oauthService.loadDiscoveryDocument(url).then(() =&gt; {
            // Do what ever you want here
        });

  }

}</code></pre></div><h2>Configure Library for Password Flow (without discovery document)</h2>
<p>In cases where you don&#39;t have an OIDC based discovery document you have to configure some more properties manually:</p>
<b>Example :</b><div><pre class="line-numbers"><code class="language-TypeScript">&#64;Component({ ... })
export class AppComponent {

  constructor(private oauthService: OAuthService) {

        // Login-Url
        this.oauthService.tokenEndpoint = &quot;https://steyer-identity-server.azurewebsites.net/identity/connect/token&quot;;

        // Url with user info endpoint
        // This endpont is described by OIDC and provides data about the loggin user
        // This sample uses it, because we don&#39;t get an id_token when we use the password flow
        // If you don&#39;t want this lib to fetch data about the user (e. g. id, name, email) you can skip this line
        this.oauthService.userinfoEndpoint = &quot;https://steyer-identity-server.azurewebsites.net/identity/connect/userinfo&quot;;

        // The SPA&#39;s id. Register SPA with this id at the auth-server
        this.oauthService.clientId = &quot;demo-resource-owner&quot;;

        // set the scope for the permissions the client should request
        this.oauthService.scope = &quot;openid profile email voucher offline_access&quot;;

        // Set a dummy secret
        // Please note that the auth-server used here demand the client to transmit a client secret, although
        // the standard explicitly cites that the password flow can also be used without it. Using a client secret
        // does not make sense for a SPA that runs in the browser. That&#39;s why the property is called dummyClientSecret
        // Using such a dummy secret is as safe as using no secret.
        this.oauthService.dummyClientSecret = &quot;geheim&quot;;

  }

}</code></pre></div><h2>Fetching an Access Token by providing the current user&#39;s credentials</h2>
<b>Example :</b><div><pre class="line-numbers"><code class="language-TypeScript">this.oauthService.fetchTokenUsingPasswordFlow(&#39;max&#39;, &#39;geheim&#39;).then((resp) =&gt; {

      // Loading data about the user
      return this.oauthService.loadUserProfile();

}).then(() =&gt; {

      // Using the loaded user data
      let claims = this.oAuthService.getIdentityClaims();
      if (claims) console.debug(&#39;given_name&#39;, claims.given_name);

})</code></pre></div><p>There is also a short form for fetching the token and loading the user profile:</p>
<b>Example :</b><div><pre class="line-numbers"><code class="language-TypeScript">this.oauthService.fetchTokenUsingPasswordFlowAndLoadUserProfile(&#39;max&#39;, &#39;geheim&#39;).then(() =&gt; {
      let claims = this.oAuthService.getIdentityClaims();
      if (claims) console.debug(&#39;given_name&#39;, claims.given_name);
});</code></pre></div><h2>Refreshing the current Access Token</h2>
<p>Using the password flow you MIGHT get a refresh token (which isn&#39;t the case with the implicit flow by design!). You can use this token later to get a new access token, e. g. after it expired.</p>
<b>Example :</b><div><pre class="line-numbers"><code class="language-TypeScript">this.oauthService.refreshToken().then(() =&gt; {
          console.debug(&#39;ok&#39;);
})</code></pre></div>
                   </div><div class="search-results">
    <div class="has-results">
        <h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
        <ul class="search-results-list"></ul>
    </div>
    <div class="no-results">
        <h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
    </div>
</div>
</div>
               <!-- END CONTENT -->
           </div>
       </div>

          <label class="dark-mode-switch">
               <input type="checkbox">
               <span class="slider">
                    <svg class="slider-icon" viewBox="0 0 24 24" fill="none" height="20" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="20" xmlns="http://www.w3.org/2000/svg">
                    <path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
                    </svg>
               </span>
          </label>

       <script>
            var COMPODOC_CURRENT_PAGE_DEPTH = 1;
            var COMPODOC_CURRENT_PAGE_CONTEXT = 'additional-page';
            var COMPODOC_CURRENT_PAGE_URL = 'using-password-flow.html';
            var MAX_SEARCH_RESULTS = 15;
       </script>

       <script>
               $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
               checkToggle(darkModeState);
               if ($darkModeToggleSwitchers.length > 0) {
                    for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
                         $darkModeToggleSwitchers[i].addEventListener('change', function (event) {
                              darkModeState = !darkModeState;
                              toggleDarkMode(darkModeState);
                         });
                    }
               }
          </script>

       <script src="../js/libs/custom-elements.min.js"></script>
       <script src="../js/libs/lit-html.js"></script>

       <script src="../js/menu-wc.js" defer></script>
       <script nomodule src="../js/menu-wc_es5.js" defer></script>

       <script src="../js/libs/bootstrap-native.js"></script>

       <script src="../js/libs/es6-shim.min.js"></script>
       <script src="../js/libs/EventDispatcher.js"></script>
       <script src="../js/libs/promise.min.js"></script>
       <script src="../js/libs/zepto.min.js"></script>

       <script src="../js/compodoc.js"></script>

       <script src="../js/tabs.js"></script>
       <script src="../js/menu.js"></script>
       <script src="../js/libs/clipboard.min.js"></script>
       <script src="../js/libs/prism.js"></script>
       <script src="../js/sourceCode.js"></script>
          <script src="../js/search/search.js"></script>
          <script src="../js/search/lunr.min.js"></script>
          <script src="../js/search/search-lunr.js"></script>
          <script src="../js/search/search_index.js"></script>
       <script src="../js/lazy-load-graphs.js"></script>


    </body>
</html>
